package com.hello.single;

/**
 * 单例模式-懒汉模式
 * 1、定义一个静态变量实例
 * 2、定义一个静态函数创建并返回实例
 * 3、私有化构造函数
 * 4、同步锁确保在多线程环境下保证单例
 * 问题
 * 1、正确的对象实例化流程：
 * a、在堆空间分配内存
 * b、执行构造方法进行初始化
 * c、将对象指向内存中分配的内存空间，也就是地址
 * 2、但是，由于编译器会对代码进行重排序优化，如果执行的顺序是acb，则也会产生错误对象。
 */
public class SynLanhanSingle2 {


    private static SynLanhanSingle2 single;

    private SynLanhanSingle2(){};

    public static SynLanhanSingle2 getInstance() {
        // 多线程访问，不做控制、不影响性能
        if (single == null) {
            // 此时，如果多个线程进入，则进入同步块
            synchronized (SynLanhanSingle2.class) {
                // 此时，第一个进入的线程判断为null，但是第二个线程进来时已经不是null了
                if (single == null) {
                    single = new SynLanhanSingle2();
                }
            }
        }
        // 如果不为null，不会影响性能，只有第一次才会影响性能
        return single;
    }


}
